package org.planaz.campusvoting.filter;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.planaz.campusvoting.common.result.Results;
import org.planaz.campusvoting.exception.ServiceException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class TokenValidateFilter implements Filter {

    private final StringRedisTemplate stringRedisTemplate;

    private final List<String> whitePathList= new ArrayList<>(){
        {
            add("/api/v1/email");
            add("/api/v1/users/login");
            add("/api/v1/users/register");
            add("/api/v1/users/resetPasswordByEmail");
        }
    };

    public TokenValidateFilter(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String requestPath = request.getRequestURI();
        if (!isPathInWhiteList(requestPath, whitePathList)) {
            String username = request.getHeader("username");
            String token = request.getHeader("token");
            Object userInfo;
            if(StringUtils.hasText(username) && StringUtils.hasText(token) && (userInfo=stringRedisTemplate.opsForHash().get("campus-voting:login:" + username, token)) != null){
                JSONObject userInfoJsonObject = JSON.parseObject(userInfo.toString());
                request.setAttribute("userId", userInfoJsonObject.get("id"));
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            returnJson(servletResponse, JSON.toJSONString(Results.failure("-1","Token is invalid")));
            return;
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    private boolean isPathInWhiteList(String requestPath, List<String> whitePathList) {
        return (!CollectionUtils.isEmpty(whitePathList) && whitePathList.stream().anyMatch(requestPath::startsWith));
    }

    private void returnJson(ServletResponse response, String json) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(json);

        } catch (IOException e) {
            log.error("response error", e);
        } finally {
            if (writer != null)
                writer.close();
        }
    }

}
